package org.lanettiesso.dubbo.simple.beans.factory.config;

import lombok.extern.slf4j.Slf4j;
import org.lanettiesso.dubbo.simple.annotation.Reference;
import org.lanettiesso.dubbo.simple.registry.MemoryRegistryCenter;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;

import java.lang.reflect.Field;

@Slf4j
public class SimpleDubboBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        Class<?> objClz;
        if (AopUtils.isAopProxy(bean)) {
            objClz = AopUtils.getTargetClass(bean);
        } else {
            objClz = bean.getClass();
        }

        try {
            for (Field field : objClz.getDeclaredFields()) {
                //判断该属性是否有 Reference 注解
                Reference reference = field.getAnnotation(Reference.class);
                if (reference != null) {
                    Class<?> fieldType = field.getType();

                    Enhancer enhancer = new Enhancer();
                    //继承被代理类
                    enhancer.setSuperclass(fieldType);

                    enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> {
                        log.info("before---------------------------------------------------");
                        //模拟远程调动服务
                        Object result = MemoryRegistryCenter.invoke(fieldType, method.getName(), objects);
                        log.info("after------------------------------------------------------");
                        return result;
                    });
                    //设置代理类对象
                    Object o = enhancer.create();
                    field.setAccessible(true);
                    //注入
                    field.set(bean, o);

                    //注册到注册中心
                    MemoryRegistryCenter.registryConsumerClazz(fieldType);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("Injection dubbo bean error.", e);
        }
        return bean;
    }
}
